package com.supplychain.scm.core.task;

import com.supplychain.scm.core.task.bean.BaseTaskParam;
import com.supplychain.scm.core.task.bean.BaseTaskResult;
import com.supplychain.scm.core.task.enums.TaskTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.util.Assert;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName AbstractTaskStrategy
 * @createTime 12:03:00 2023/04/01
 */
@Slf4j
public abstract class AbstractTaskStrategy<T extends BaseTaskParam, R extends BaseTaskResult> implements ITaskStrategy {

    /**
     * 异步任务类型
     * @return
     */
    protected abstract TaskTypeEnum taskType();

    /**
     * 业务定义的业务类型
     * @return
     */
    protected abstract String bizTaskType();

    /**
     * 业务处理之前处理
     *
     * @param t
     * @return
     */
    protected Object beforeHandler(T t) {
        return null;
    }

    /**
     * 策略业务处理方法定义
     *
     * @param t
     * @param beforeResult
     * @return
     */
    protected R handler(T t,Object beforeResult) {
        throw new UnsupportedOperationException();
    }

    /**
     * 业务处理之后处理
     *
     * @param t
     * @param r
     * @return
     */
    protected Object afterHandler(T t, R r) {
        return null;
    }

    /**
     * 异常处理器
     *
     * @param t
     * @return
     */
    protected Object exceptionHandler(T t, R r) {
        return null;
    }

    /**
     * 最终处理器
     *
     * @param t
     * @return
     */
    protected Object finallyHandler(T t, R r) {
        return null;
    }

    /**
     * 拆分任务
     * @param t
     * @return
     */
    public R splitTaskHandler(T t){ return null; }

    public R taskAsyncHandler(T t) throws Exception{
        R handler = null;
        try {
            Object beforeResult = this.beforeHandler(t);
            handler = this.handler(t,beforeResult);
            this.afterHandler(t, handler);
        } catch (Exception e) {
            this.exceptionHandler(t, handler);
            log.warn("策略处理器发生异常:{}", ExceptionUtils.getStackTrace(e));
            throw e;
        } finally {
            this.finallyHandler(t, handler);
        }
        return handler;
    }

    @Override
    public final boolean support(Object... args) {
        if (ObjectUtils.isNotEmpty(args)) {
            return Arrays.stream(args).anyMatch(item -> item.equals(this.bizTaskType())) &&
                    Arrays.stream(args).anyMatch(item -> item instanceof String && Objects.equals(this.taskType().getValue(),(String) item));
        }
        return Boolean.FALSE;
    }

    public final Class<T> paramClass() {
        Class<T> clazz = null;
        Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
        for (Type type : types) {
            Class<T> modelClass = (Class<T>) type;
            Class<? super T> superclass = modelClass.getSuperclass();
            if (Objects.nonNull(superclass) && BaseTaskParam.class.isAssignableFrom(superclass)) {
                clazz = modelClass;
                break;
            }
        }
        Assert.notNull(clazz, "undefined generics");
        return clazz;
    }
}
